<?php
/**
 * 用Redis记录Context
 */
declare(strict_types=1);

namespace Libraries\ContextDrivers;

use Libraries\Connections\RedisConn;

class ContextInRedis
{
    private static $strRedisName = 'context';

    private static $intLife = 3600;

    private static function getKey(string $strId, string $strKey): string
    {
        return 'context:' . md5($strId . '|' . $strKey);
    }

    public static function get(string $strId, string $strKey)
    {
        $re = self::getMulti([$strId => [$strKey]]);
        return $re ? ($re[$strId][$strKey] ?? null) : null;
    }

    public static function getMulti(array $arrIdKey): array
    {
        $arrRe = [];
        if (!$arrIdKey) {
            return $arrRe;
        }
        $arrTemp = [];
        $arrRealKey = [];
        $intCnt = 0;
        foreach ($arrIdKey as $strId => $arrKey) {
            foreach ($arrKey as $strKey) {
                $arrTemp[$intCnt] = [$strId, $strKey];
                $arrRealKey[$intCnt++] = self::getKey($strId, $strKey);
            }
        }
        $objRedis = RedisConn::get(self::$strRedisName);
        if ($objRedis) {
            $arrData = $objRedis->mget($arrRealKey);
            RedisConn::put($objRedis, self::$strRedisName);
            if (is_array($arrData) && count($arrData) == $intCnt) {
                foreach ($arrData as $intI => $str) {
                    [$strId, $strKey] = $arrTemp[$intI];
                    $arrRe[$strId][$strKey] = $str ? unserialize($str) : $str;
                }
            }
        } else {
            RedisConn::put(null, self::$strRedisName);
        }
        return $arrRe;
    }

    public static function set(string $strId, string $strKey, $mixVal): bool
    {
        return self::setMulti([$strId => [$strKey => $mixVal]]);
    }

    public static function setMulti(array $arrIdKeyData): bool
    {
        $blnRe = false;
        if (!$arrIdKeyData) {
            return $blnRe;
        }
        $objRedis = RedisConn::get(self::$strRedisName);
        if ($objRedis) {
            $blnRe = true;
            foreach ($arrIdKeyData as $strId => $arrKeyData) {
                foreach ($arrKeyData as $strKey => $mixVal) {
                    if (!$blnRe) {
                        break;
                    }
                    $blnRe = $objRedis->setex(self::getKey($strId, $strKey), self::$intLife, serialize($mixVal));
                }
            }
            RedisConn::put($objRedis, self::$strRedisName);
        } else {
            RedisConn::put(null, self::$strRedisName);
        }
        return $blnRe;
    }

    public static function del(string $strId, string $strKey): bool
    {
        return self::delMulti([$strId => [$strKey]]);
    }

    public static function delMulti(array $arrIdKey): bool
    {
        if (!$arrIdKey) {
            return false;
        }
        $intRe = 0;
        $arrRealKey = [];
        foreach ($arrIdKey as $strId => $arrKey) {
            foreach ($arrKey as $strKey) {
                array_push($arrRealKey, self::getKey($strId, $strKey));
            }
        }
        $objRedis = RedisConn::get(self::$strRedisName);
        if ($objRedis) {
            $intRe = $objRedis->del($arrRealKey);
            RedisConn::put($objRedis, self::$strRedisName);
            is_int($intRe) || $intRe = 0;
        } else {
            RedisConn::put(null, self::$strRedisName);
        }
        return $intRe > 0;
    }
}
